﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Windows;
using AuchanScan.Datas;
using AuchanScan.Models;
using AuchanScan.Services;
using Microsoft.Devices;
using WP7.ScanBarCode;
using AuchanScan.Tools;

namespace AuchanScan.ViewModels
{
    public class MainViewModel : INotifyPropertyChanged
    {
        public MainViewModel()
        {
            Datas = UserData.GetInstance();
            LastTrophies = new ObservableCollection<TrophyBase>();
            if (Datas.Trophies.Any(t => t.HasBeenWon))
            {
                var trophies = Datas.Trophies.Where(t => t.HasBeenWon);
                foreach (var item in trophies)
                    LastTrophies.Add(item);
            }
        }

        private bool passed;
        void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
        {
            TestConnection();
        }

        private void TestConnection()
        {
            WebClient wc = new WebClient();
            wc.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.MinValue.ToString();
            wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
            wc.DownloadStringAsync(new Uri(Config.BASE_URI + "/auchan/ping.html?", UriKind.Absolute));
        }

        void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {

            if (e.Cancelled || e.Error != null)
                return;
            if (e.Result != "TRUE")
                return;
            if (!passed)
            {
                passed = true;

                Deployment.Current.Dispatcher.BeginInvoke(() => {
                    NavigationServiceHelper.Instance.NavigateTo(new Uri("/Views/SyncPage.xaml", UriKind.Relative));
                });
            }
        }


        public UserData Datas { get; set; }

        private Achat _currentProduct;
        public Achat CurrentProduct
        {
            get { return _currentProduct; }
            set
            {
                _currentProduct = value;
                this.RaisePropertyChanged("CurrentProduct");
            }
        }

        public bool HasProduct
        {
            get { return Datas.Courses.Count > 0 ? false : true; }
        }

        public ObservableCollection<TrophyBase> LastTrophies { get; set; }
        //{
        //    get
        //    {
        //        var trophiesList = Datas.Trophies.Where(t => t.HasBeenWon).OrderByDescending(c => c.GotDate).ToList();

        //        if (trophiesList != null && trophiesList.Count > 0)
        //        {
        //            var trophies = new ObservableCollection<TrophyBase>();
        //            return trophies;
        //        }

        //        return new ObservableCollection<TrophyBase>(); ;
        //    }
        //}

        public double TotalPrice
        {
            get { return Datas.Courses.Select((c) => c.TotalPrice).Sum(); }
        }


        public double NbrArticles
        {
            get { return Datas.Courses.Select((c) => c.Quantity).Sum(); }
        }


        public double TicketResto
        {
            get { return Datas.Courses.Where((c) => c.Product.IsTicketRestoCompliant).Select((c) => c.TotalPrice).Sum(); }
        }

        public double TVA
        {
            get { return Datas.Courses.Select((c) => c.TVA).Sum(); }
        }

        public double TRPercent
        {
            get { return 100 * TicketResto / (Datas.TicketRestoValue * 2); }
        }

        public void ScanAnArticle()
        {
            try
            {
                BarCodeManager.StartScan(
                    barcode =>
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() => {
                            VibrateController.Default.Start(TimeSpan.FromMilliseconds(200));
                            AddArticleWithBarCode(long.Parse(barcode));
                            NavigationServiceHelper.Instance.GoBack();
                        });
                    },
                    exc => { Deployment.Current.Dispatcher.BeginInvoke(() => { MessageBox.Show(exc.Message); }); }
                    );
            }
            catch (Exception e){}
        }

        public void ScanAnArticleForRemove()
        {
            try
            {
                BarCodeManager.StartScan(
                    barcode =>
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            VibrateController.Default.Start(TimeSpan.FromMilliseconds(200));
                            RemoveArticleWithBarCode(long.Parse(barcode));
                            NavigationServiceHelper.Instance.GoBack();
                        });
                    },
                    exc => { Deployment.Current.Dispatcher.BeginInvoke(() => { MessageBox.Show(exc.Message); }); }
                    );
            }
            catch (Exception e)
            {
            }
        }

        private void AddArticleWithBarCode(long barcode)
        {
            Achat achatStillExists = Datas.Courses.FirstOrDefault((achat) => achat.Product.Barcode == barcode);
            if (achatStillExists != null)
            {
                achatStillExists.AddQuantity(1);
            }
            else
            {
                Product product = ProductDatabase.Instance.SearchProductFromBarcode(barcode);
                if (product == null)
                {
                    MessageBox.Show("impossible de trouver l'article dans la base de données");
                }
                else
                {
                    var achat = new Achat { Quantity = 1, Product = product };
                    SearchPromo(achat);
                    Datas.Courses.Add(achat);
                    this.RaisePropertyChanged("HasProduct");
                }
            }
            ComputePrice();
        }

        private void SearchPromo(Achat achat)
        {
            int id = achat.Product.Id;
            if (PromotionService.Current.Promotions == null || PromotionService.Current.Promotions.Offres == null)
                return;
            Offre promo = PromotionService.Current.Promotions.Offres.FirstOrDefault((o) => o.Id == id);
            if (promo != null)
            {
                achat.Promotion = promo;
            }
        }


        private void RemoveArticleWithBarCode(long barcode)
        {
            Achat achatStillExists = Datas.Courses.FirstOrDefault((achat) => achat.Product.Barcode == barcode);
            if (achatStillExists != null)
            {
                achatStillExists.AddQuantity(-1);
                if (achatStillExists.Quantity == 0)
                {
                    Datas.Courses.Remove(achatStillExists);
                }
            }

            ComputePrice();
        }


        private void ComputePrice()
        {
            RaisePropertyChanged("TicketResto");
            RaisePropertyChanged("TVA");
            RaisePropertyChanged("NbrArticles");
            RaisePropertyChanged("TotalPrice");
        }

        internal void RemoveItem(Achat achat)
        {
            Datas.Courses.Remove(achat);
            ComputePrice();
        }

        internal void ChangeQuantity(Achat _selectedAchat, int p)
        {
            _selectedAchat.AddQuantity(p);
            ComputePrice();
        }

        internal void AddToTheToBuyList(Product product)
        {
            if (!Datas.ToBuyList.Any((p) => p.Barcode == product.Barcode))
                Datas.ToBuyList.Add(product);
        }

        #region PropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(String name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }

        #endregion

        internal void ValidBasket()
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => {

                Datas.Histories.Add(new History() { Achats = Datas.Courses.ToList(), Date = DateTime.Now });
                var trophiesResult = TrophyHelper.Current.CheckTrophies(Datas.Courses.ToList());
                if (trophiesResult.Count > 0)
                {
                    for (int i = 0; i < Datas.Trophies.Count; i++)
                    {
                        var trophy = Datas.Trophies[i];
                        if (trophiesResult.FirstOrDefault(t => t.Id == trophy.Id) != null) {
                            trophy.GotDate = DateTime.Now;
                            trophy.HasBeenWon = true;
                            Datas.Trophies[i] = trophy;
                        }
                    }

                    LastTrophies.Clear();
                    var itemsToAdd = Datas.Trophies.OrderByDescending(c => c.GotDate).Take(3).ToList();
                    foreach (var item in itemsToAdd)
                        LastTrophies.Add(item);
                }

                List<Product> products = new List<Product>();

                var achats = Datas.Courses;
                for (int i = 0; i < achats.Count; i++)
                {
                    if (Datas.ToBuyList.FirstOrDefault(a => a.Id == achats[i].Product.Id) == null)
                    {
                        products.Add(achats[i].Product);
                    }
                }

                Datas.ToBuyList = new ObservableCollection<Product>(products);

                while (Datas.Courses.Count != 0)
                {
                    Datas.Courses.RemoveAt(0);
                }
            });
        }

        internal void StartTestUsb()
        {
            TestConnection();
            NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged);
        }

        internal void EmptyCard()
        {
            var course = this.Datas.Courses;
            while (course.Count != 0)
                course.RemoveAt(0);

            ComputePrice();
        }
    }
}
